
#include <Inklude/ikCTcpClient.h>
#include <Inklude/ikCTcpServer.h>
#include <Inklude/Internal/ikCTcpBoost.h>

using namespace Inklude;

ikCTcpClient::ikCTcpClient()
{
    m_pTcp.reset(new Internal::ikCTcpBoost);
    m_bConnected = false;
}

ikCTcpClient::ikCTcpClient(std::shared_ptr<Inklude::Internal::ikCTcpBoost> pBoostTcp)
{
    m_pTcp = pBoostTcp;
    //m_pTcp = reset(pBoostTcp.get());
}

void ikCTcpClient::SetDestinationAddress(const char* IPAddress, unsigned int nPort)
{
    m_pTcp->SetDestinationAddress(IPAddress, nPort);
}

bool ikCTcpClient::ConnectToServer()
{
    return m_bConnected = m_pTcp->ConnectToServer();
}

void ikCTcpClient::AsyncConnectToServer(AsyncHandler endHandler)
{
    m_pTcp->AsyncConnectToServer(endHandler);
    m_pTcp->Run();
}

size_t ikCTcpClient::Wrtie(void* pBuffer, size_t nDataSize)
{
    return m_pTcp->SyncWrite(pBuffer, nDataSize);;
}

size_t ikCTcpClient::Read(void* pBuffer, size_t nDataSize)
{
    return m_pTcp->SyncRead(pBuffer, nDataSize);
}

void ikCTcpClient::AsyncWrite(void* pBuffer, size_t nDataSize, AsyncHandler endHandler)
{
    m_pTcp->AsyncWrite(pBuffer, nDataSize, endHandler);
    m_pTcp->Run();
}

void ikCTcpClient::AsyncRead(void* pBuffer, size_t nDataSize, AsyncHandler endHandler)
{
    m_pTcp->AsyncRead(pBuffer, nDataSize, endHandler);
    m_pTcp->Run();
}

bool ikCTcpClient::IsConnected()
{
    return m_bConnected;
}

void ikCTcpClient::_internal_set_con_setting(int password)
{
    if (password == 23463232)
    {
        m_bConnected = true;
    }
}

// ---------------------------------------------------------------
// --- ASync Routine
// ---------------------------------------------------------------
ikCTcpClientASync::~ikCTcpClientASync()
{
}

void ikCTcpClientASync::Initialize(unsigned int nRecvPort)
{
    m_pServer.reset(new ikCTcpServer);
    m_pServer->OpenServer(nRecvPort);
    m_pTcp = NULL;
}

void ikCTcpClientASync::SetDestinationAddress(const char* IPAddress, unsigned int nPort)
{
    m_pServer = NULL;
    if (NULL == m_pTcp)
    {
        m_pTcp.reset(new ikCTcpClient);
    }
    m_pTcp->SetDestinationAddress(IPAddress, nPort);
}

size_t ikCTcpClientASync::Send(const void* pBuffer, size_t nDataSize, AsyncHandler endHandler) 
{
    assert(endHandler != NULL && "You should provide AsyncHandler for ASync routine");
    assert( !(endHandler._Expired()) && "Given AsyncHandler already has been expired");
    if (NULL != m_pTcp && !m_pTcp->IsConnected())
    {
        AsyncHandler _pHandler(new std::function<void(size_t)>([=](size_t param)
        {
            m_pTcp->_internal_set_con_setting(23463232);
            m_pTcp->AsyncWrite(const_cast<void*>(pBuffer), nDataSize, endHandler);
        }
        ));
        
        m_pTcp->AsyncConnectToServer(_pHandler);
    }
    else
    {
        m_pTcp->AsyncWrite(const_cast<void*>(pBuffer), nDataSize, endHandler);
    }
    return 0;
}

size_t ikCTcpClientASync::Receive(void* pBuffer, const size_t nDataSize, AsyncHandler endHandler) 
{
    assert(endHandler != NULL && "You should provide AsyncHandler for ASync routine");
    assert( !(endHandler._Expired()) && "Given AsyncHandler already has been expired");
    if (NULL != m_pServer && NULL == m_pTcp)
    {
        ikCTcpServer::CheckNewConnectionHandler _pHandler(new std::function<void(ikCTcpClientPtr)>([=](ikCTcpClientPtr _pClient)
        {
            m_pTcp = _pClient;
            m_pTcp->AsyncRead(pBuffer, nDataSize, endHandler);
        }
        ));        
        m_pServer->AsyncCheckNewConnection(_pHandler);
    }
    else
    {
        m_pTcp->AsyncRead(pBuffer, nDataSize, endHandler);
    }
    return 0;
}

void ikCTcpClientASync::Close()
{
}

// ---------------------------------------------------------------
// --- Sync Routine
// ---------------------------------------------------------------

ikCTcpClientSync::~ikCTcpClientSync()
{
}

void ikCTcpClientSync::Initialize(unsigned int nRecvPort)
{
    m_pServer.reset(new ikCTcpServer);
    m_pServer->OpenServer(nRecvPort);
    m_pTcp = NULL;
}

void ikCTcpClientSync::SetDestinationAddress(const char* IPAddress, unsigned int nPort)
{
    m_pServer = NULL;
    if (NULL == m_pTcp)
    {
        m_pTcp.reset(new ikCTcpClient);
    }
    m_pTcp->SetDestinationAddress(IPAddress, nPort);
}

size_t ikCTcpClientSync::Send(const void* pBuffer, size_t nDataSize, AsyncHandler endHandler)
{
    assert(endHandler == NULL && "You should not put AsyncHandler for Sync routine");
    size_t _retVal = 0;

    if (NULL != m_pTcp && !m_pTcp->IsConnected())
    {
        m_pTcp->ConnectToServer();
    }

    if (NULL != m_pTcp && m_pTcp->IsConnected())
    {
        _retVal = m_pTcp->Wrtie(const_cast<void*>(pBuffer), nDataSize);
    }
    return _retVal;
}

size_t ikCTcpClientSync::Receive(void* pBuffer, const size_t nDataSize, AsyncHandler endHandler)
{
    assert(endHandler == NULL && "You should not put AsyncHandler for Sync routine");
    assert(endHandler == NULL);
    size_t _retVal = 0;

    if (NULL != m_pServer && NULL == m_pTcp)
    {
        m_pTcp = m_pServer->CheckNewConnection();
    }
    if (NULL != m_pTcp)
    {
        _retVal = m_pTcp->Read(pBuffer, nDataSize);
    }
    return _retVal;
}

void ikCTcpClientSync::Close()
{
    
}

